<script setup lang="ts">
import type {
  ColumnType,
  FilterValue,
  SorterResult,
  TableCurrentDataSource,
  TableRowSelection
} from "ant-design-vue/lib/table/interface";
import {DownOutlined} from "@ant-design/icons-vue";
import type {ActionColumn, ActionItem} from "@/components/CatTable/column/ActionColumn";
import {onMounted, onUnmounted, type PropType, ref, useAttrs} from "vue";
import {defaultColumnProperties} from "@/components/CatTable/ColumnTypes";
import type {DictColumn} from "@/components/CatTable/column/DictColumn";
import type {CatColumn} from "@/components/CatTable/column/CatColumn";
import type {TablePaginationConfig} from "ant-design-vue/es";
import CrudController, {type CrudConfig} from "@/components/CatCrud/CrudController";

const props = defineProps({
  config: {
    type: Object as PropType<CrudConfig<any, any, any>>,
    required: true
  },
  controller: {
    type: Object as PropType<CrudController<any, any, any, any, any>>,
    required: false
  },
  actions: {
    type: Array<ActionColumn>,
    required: false,
    default: []
  },
  selection: {
    type: Boolean,
    default: true
  },
  headerHeight: {
    type: Number,
    default: 60
  },
  tableHeight: {
    type: String
  },
  multiple: {
    type: Boolean,
    default: true
  }
});
const emit = defineEmits(["switchChange", "actionClick", 'selectionChange', 'tableChange']);

function onSwitchChange(dataIndex: string, value: boolean, record: any, column: ColumnType) {
  props.controller?.onSwitchChange(dataIndex, value, record, column);
  emit('switchChange', dataIndex, value, record, column);
}

function onTableChange(pagination: TablePaginationConfig, filters: Record<string, FilterValue | null>,
                       sorter: SorterResult<any> | SorterResult<any>[], extra: TableCurrentDataSource<any>) {
  props.controller?.onTableChange(pagination, filters, sorter, extra);
  emit('tableChange', pagination, filters, sorter, extra);
}

function onActionClick(key: string, record: any, column: ActionColumn, item: ActionItem) {
  props.controller?.onActionClick(key, record, column, item);
  emit('actionClick', key, record, column, item);
}

function lookup(column: DictColumn, record: any): any {
  if (column.data) {
    const dataIndex = String(column.sortIndex || column.dataIndex);
    const key = record[dataIndex];
    const item = key !== undefined && column.data
        /*id类型可能不一致，需要强转*/
        .find((row) => String(row.id) === String(key));
    return item ? item.name : key;
  } else {
    const dataIndex = String(column.dataIndex);
    const key = record[dataIndex];
    return key;
  }
}

const rowSelection: TableRowSelection = {
  type: props.multiple ? 'checkbox' : 'radio',
  fixed: "left",
  checkStrictly: false,
  onChange: (selectedRowKeys: (string | number)[], selectedRows: any[]) => {
    props.controller?.onSelectionChange(selectedRowKeys, selectedRows);
    emit("selectionChange", selectedRowKeys, selectedRows);
  },
};


const catTable = ref<HTMLElement>();
const scrollHeight = ref<number | string>();

function calculateScrollHeight() {
  scrollHeight.value = props.tableHeight || catTable.value!.offsetHeight - props.headerHeight;
  if (props.tableHeight) {
    catTable.value!.style.height = props.tableHeight;
  }
}

onUnmounted(() => {
  window.removeEventListener('resize', calculateScrollHeight)
})

onMounted(() => {
  calculateScrollHeight();
  window.addEventListener('resize', calculateScrollHeight);
  const columns = <CatColumn[]>useAttrs()['columns'];
  props.actions.forEach(action => {
    const column = columns.find(column => column.title === action.title)
    // 在重新渲染时，会重复执行mount
    if (!column) {
      columns.push(action)
    }
  });
  defaultColumnProperties(columns);
})

</script>

<template>
  <div class="cat-table" ref="catTable">
    <a-table row-key="id"
             :scroll="{y: scrollHeight }"
             :row-selection="selection ? rowSelection: undefined"
             :pagination="false"
             :data-source="config.page!.content"
             :columns="config.columns"
             :loading="config.loading"
             @change="onTableChange"
             v-bind="$attrs"
             bordered
    >
      <template #bodyCell="{text, record, index, column}">
        <!--渲染字典-->
        <template v-if="(column as CatColumn).type === 'dict'">
          {{ lookup(column, record) }}
        </template>
        <!--渲染开关-->
        <template v-else-if="(column as CatColumn).type === 'switch'">
          <a-switch
              :checked="record[column.dataIndex as string]"
              @change="onSwitchChange(column.dataIndex, record[column.dataIndex as string], record, column)"
          ></a-switch>
        </template>
        <!--渲染按钮-->
        <template v-else-if="(column as CatColumn).type === 'action'">
        <span v-for="(item, index) in (column as ActionColumn).items">
          <a-popconfirm v-if="item.confirm" :title="item.confirm"
                        @confirm="onActionClick(item.key, record, column, item)">
            <a style="margin: 0 15px 0 0" class="theme-table-action-btn danger">{{ item.title }}</a>
          </a-popconfirm>
          <a v-else style="margin: 0 15px 0 0" class="theme-table-action-btn"
             @click="onActionClick(item.key, record, column, item)"> {{ item.title }}</a>
        </span>
          <a-dropdown trigger="click" v-if="(column as ActionColumn).more">
            <a class="ant-dropdown-link">更多
              <down-outlined/>
            </a>
            <template #overlay>
              <a-menu>
                <a-menu-item v-for="item in (column as ActionColumn).more" :key="item.key">
                  <a-popconfirm v-if="item.confirm" :title="item.confirm"
                                @confirm="onActionClick(item.key, record, column, item)">
                    <a class="theme-table-action-btn danger">{{ item.title }}</a>
                  </a-popconfirm>
                  <a v-else class="theme-table-action-btn"
                     @click="onActionClick(item.key, record, column, item)"> {{ item.title }}</a>
                </a-menu-item>
              </a-menu>
            </template>
          </a-dropdown>
        </template>
        <!--插槽？-->
        <slot name="bodyCell" :text="text" :record="record" :index="index" :column="column"></slot>
      </template>
    </a-table>
  </div>
</template>
<style scoped lang="less">
.cat-table {
  height: 100%;
}
</style>